package com.ruoyi.project.system.task;

import com.ruoyi.project.system.domain.Tasks;
import com.ruoyi.project.system.domain.TaskCycleDeadlines;
import com.ruoyi.project.system.domain.UserTaskCompletion;
import com.ruoyi.project.system.domain.TaskRecipients;
import com.ruoyi.project.system.service.ITasksService;
import com.ruoyi.project.system.mapper.TaskCycleDeadlinesMapper;
import com.ruoyi.project.system.service.IUserTaskCompletionService;
import com.ruoyi.project.system.service.ITaskRecipientsService;
import com.ruoyi.project.system.mapper.UserTaskCompletionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.project.system.domain.ReminderRules;

/**
 * 定时创建下一个任务周期的Job
 */
@Component("createNextCycleJob")
public class CreateNextCycleJob {

    @Autowired
    private ITasksService tasksService;

    @Autowired
    private TaskCycleDeadlinesMapper taskCycleDeadlinesMapper;

    @Autowired
    private com.ruoyi.project.system.service.IReminderRulesService reminderRulesService;

    @Autowired
    private com.ruoyi.project.monitor.service.ISysJobService sysJobService;

    @Autowired
    private IUserTaskCompletionService userTaskCompletionService;

    @Autowired
    private ITaskRecipientsService taskRecipientsService;

    @Autowired
    private UserTaskCompletionMapper userTaskCompletionMapper;

    /**
     * 定时任务入口
     * 
     * @param taskId 任务ID
     */
    public void execute(Integer taskId) {
        Long taskIdLong = taskId.longValue();
        // 查询任务
        Tasks task = tasksService.selectTasksById(taskIdLong);
        if (task == null) {
            return;
        }
        // 查询当前周期
        QueryWrapper<TaskCycleDeadlines> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id", taskId);
        queryWrapper.eq("is_current", 1);
        TaskCycleDeadlines lastCycle = taskCycleDeadlinesMapper.selectOne(queryWrapper);
        if (lastCycle == null) {
            return;
        }
        // 1. 将上一个周期is_current设为0
        lastCycle.setIsCurrent(0);
        taskCycleDeadlinesMapper.updateById(lastCycle);

        // 2. 获取ReminderRules
        ReminderRules reminderRule = reminderRulesService
                .selectReminderRulesByTaskId(taskIdLong);
        if (reminderRule == null) {
            return;
        }

        // 3. 计算新周期的开始、结束、截止时间、nextTrigger
        TaskCycleDeadlines newCycle = new TaskCycleDeadlines();
        newCycle.setTaskId(taskIdLong);
        newCycle.setCycleType(lastCycle.getCycleType());
        newCycle.setCycleStart(lastCycle.getCycleEnd());
        newCycle.setIsCurrent(1);
        newCycle.setCreatedAt(new java.util.Date());
        newCycle.setUpdatedAt(new java.util.Date());

        java.util.Calendar cal = java.util.Calendar.getInstance();
        java.util.Calendar deadlinecal = java.util.Calendar.getInstance();
        cal.setTime(lastCycle.getCycleEnd());
        deadlinecal.setTime(lastCycle.getDeadline());
        String frequency = reminderRule.getFrequency();
        switch (frequency) {
            case "daily":
                cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                deadlinecal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
            case "weekly":
                cal.add(java.util.Calendar.WEEK_OF_YEAR, 1);
                deadlinecal.add(java.util.Calendar.WEEK_OF_YEAR, 1);
                break;
            case "monthly":
                cal.add(java.util.Calendar.MONTH, 1);
                deadlinecal.add(java.util.Calendar.MONTH, 1);
                break;
            case "yearly":
                cal.add(java.util.Calendar.YEAR, 1);
                deadlinecal.add(java.util.Calendar.YEAR, 1);
                break;
            default:
                cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                deadlinecal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
        }
        if (cal.getTime().after(task.getEffectiveEnd())) {
            newCycle.setCycleEnd(task.getEffectiveEnd());
        } else {
            newCycle.setCycleEnd(cal.getTime());
        }
        newCycle.setDeadline(deadlinecal.getTime());

        // 判断是否会有下一周期被创建
        boolean willCreateNextCycle = checkIfWillCreateNextCycle(task, lastCycle.getDeadline(), reminderRule);
        // 只有在会创建下一周期时才设置nextTrigger
        if (willCreateNextCycle) {
            java.util.Date nextTrigger = calculateNextTrigger(reminderRule, newCycle.getCycleStart());
            newCycle.setNextTrigger(nextTrigger);
        } else {
            // 如果不会创建下一周期，设置nextTrigger为null
            newCycle.setNextTrigger(null);
        }

        // 插入新周期
        taskCycleDeadlinesMapper.insert(newCycle);

        // 6. 为新周期创建所有接收人的UserTaskCompletion记录
        createUserTaskCompletionsForNewCycle(taskIdLong, newCycle.getId());

        // 7. 预约下次周期创建
        // 计算下一个周期的开始和结束时间
        java.util.Calendar nextEndCal = java.util.Calendar.getInstance();
        nextEndCal.setTime(newCycle.getDeadline());
        switch (reminderRule.getFrequency()) {
            case "daily":
                nextEndCal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
            case "weekly":
                nextEndCal.add(java.util.Calendar.WEEK_OF_YEAR, 1);
                break;
            case "monthly":
                nextEndCal.add(java.util.Calendar.MONTH, 1);
                break;
            case "yearly":
                nextEndCal.add(java.util.Calendar.YEAR, 1);
                break;
            default:
                nextEndCal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
        }
        // 下一个周期的开始时间就是当前周期的结束时间
        java.util.Date nextCycleStart = newCycle.getCycleEnd();
        java.util.Date nextCycleEnd = nextEndCal.getTime();
        scheduleNextCycle(taskIdLong, nextCycleStart, nextCycleEnd);
    }

    /**
     * 为新周期创建所有接收人的UserTaskCompletion记录
     * 
     * @param taskId  任务ID
     * @param cycleId 周期ID
     */
    private void createUserTaskCompletionsForNewCycle(Long taskId, Integer cycleId) {
        try {
            // 查询任务的所有接收人
            TaskRecipients recipientQuery = new TaskRecipients();
            recipientQuery.setTaskId(taskId);
            List<TaskRecipients> recipients = taskRecipientsService.selectTaskRecipientsList(recipientQuery);

            if (recipients != null && !recipients.isEmpty()) {
                for (TaskRecipients recipient : recipients) {
                    // 为每个接收人创建UserTaskCompletion记录
                    UserTaskCompletion userCompletion = new UserTaskCompletion();
                    userCompletion.setTaskId(taskId.intValue());
                    userCompletion.setUserId(recipient.getUserId());
                    userCompletion.setCycleId(cycleId);
                    userCompletion.setStatus("进行中");
                    userCompletion.setCreatedAt(new Date());
                    userCompletion.setUpdatedAt(new Date());

                    // 插入用户任务完成状态记录
                    userTaskCompletionMapper.insert(userCompletion);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算下次触发时间（参考AppController的实现）
     */
    private java.util.Date calculateNextTrigger(com.ruoyi.project.system.domain.ReminderRules reminderRule,
            java.util.Date baseDate) {
        java.util.Calendar now = java.util.Calendar.getInstance();
        java.util.Calendar next = java.util.Calendar.getInstance();
        next.setTime(baseDate);
        // 设置时间
        if (reminderRule.getTimeOfDay() != null) {
            java.util.Calendar timeCalendar = java.util.Calendar.getInstance();
            timeCalendar.setTime(reminderRule.getTimeOfDay());
            next.set(java.util.Calendar.HOUR_OF_DAY, timeCalendar.get(java.util.Calendar.HOUR_OF_DAY));
            next.set(java.util.Calendar.MINUTE, timeCalendar.get(java.util.Calendar.MINUTE));
            next.set(java.util.Calendar.SECOND, 0);
            next.set(java.util.Calendar.MILLISECOND, 0);
        }
        String frequency = reminderRule.getFrequency();
        switch (frequency) {
            case "daily":
                next.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
            case "weekly":
                next.add(java.util.Calendar.WEEK_OF_YEAR, 1);
                break;
            case "monthly":
                next.add(java.util.Calendar.MONTH, 1);
                break;
            case "yearly":
                next.add(java.util.Calendar.YEAR, 1);
                break;
            default:
                next.add(java.util.Calendar.DAY_OF_YEAR, 1);
                break;
        }
        return next.getTime();
    }

    /**
     * 预约下一个任务周期的创建
     */
    private void scheduleNextCycle(Long taskId, java.util.Date nextCycleStart, java.util.Date nextCycleEnd) {
        try {
            // 检查任务是否在有效期内
            Tasks task = tasksService.selectTasksById(taskId);
            if (task == null) {
                return;
            }
            // 检查任务是否激活
            if (task.getIsActive() == null || task.getIsActive() != 1) {
                return;
            }
            // 检查任务生效结束时间（为空表示永久有效）
            if (task.getEffectiveEnd() != null) {
                // 如果下个周期的开始时间已超过任务有效期，不预约
                if (nextCycleStart.after(task.getEffectiveEnd())) {
                    return;
                }
                // 如果下个周期的结束时间超过任务有效期，不预约
                if (nextCycleEnd.after(task.getEffectiveEnd())) {
                    return;
                }
            }
            String cron = dateToCron(nextCycleStart);
            com.ruoyi.project.monitor.domain.SysJob job = new com.ruoyi.project.monitor.domain.SysJob();
            job.setJobName("CreateNextCycleJob_" + taskId);
            job.setJobGroup("TaskCycle");
            job.setInvokeTarget("createNextCycleJob.execute(" + taskId + ")");
            job.setCronExpression(cron);
            job.setMisfirePolicy("1");
            job.setConcurrent("0");
            job.setStatus("0");
            job.setRemark("任务ID: " + taskId + " 的下周期创建");
            sysJobService.insertJob(job);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将 Date 转换为 cron 表达式（精确到分钟）
     */
    private String dateToCron(java.util.Date date) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(date);
        int second = calendar.get(java.util.Calendar.SECOND);
        int minute = calendar.get(java.util.Calendar.MINUTE);
        int hour = calendar.get(java.util.Calendar.HOUR_OF_DAY);
        int day = calendar.get(java.util.Calendar.DAY_OF_MONTH);
        int month = calendar.get(java.util.Calendar.MONTH) + 1;
        int year = calendar.get(java.util.Calendar.YEAR);
        return String.format("%d %d %d %d %d ? %d", second, minute, hour, day, month, year);
    }

    /**
     * 判断是否会创建下一周期（根据上一周期截止时间推算）
     */
    private boolean checkIfWillCreateNextCycle(Tasks task, java.util.Date lastCycleDeadline,
            ReminderRules reminderRule) {
        if (task == null) {
            return false;
        }
        // 检查任务是否激活
        if (task.getIsActive() == null || task.getIsActive() != 1) {
            return false;
        }
        // 检查任务生效结束时间（为空表示永久有效）
        if (task.getEffectiveEnd() != null) {
            // 计算下个周期的截止时间（基于上一周期截止时间）
            java.util.Calendar deadlineCal = java.util.Calendar.getInstance();
            deadlineCal.setTime(lastCycleDeadline);
            switch (reminderRule.getFrequency()) {
                case "daily":
                    deadlineCal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                    break;
                case "weekly":
                    deadlineCal.add(java.util.Calendar.WEEK_OF_YEAR, 1);
                    break;
                case "monthly":
                    deadlineCal.add(java.util.Calendar.MONTH, 1);
                    break;
                case "yearly":
                    deadlineCal.add(java.util.Calendar.YEAR, 1);
                    break;
                default:
                    deadlineCal.add(java.util.Calendar.DAY_OF_YEAR, 1);
                    break;
            }
            java.util.Date nextCycleDeadline = deadlineCal.getTime();
            // 如果下个周期的截止时间超过任务有效期，不创建
            if (nextCycleDeadline.after(task.getEffectiveEnd())) {
                return false;
            }
        }
        return true;
    }
}